package preprocess;

import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.*;

import utils.config.Config;

import data.*;



public class RankEngine {
	
	private String[] ERLANG_FILES;
	private CityArea AREA;
	private String[] CAT_SET;
	private String DB;
	
	public static void main(String[] args) throws Exception {
		RankEngine re = new RankEngine();
		re.createRankings();
	}
	
	public RankEngine() {
		
		Config config = new Config(this.getClass().getSimpleName()+".ser"); 
				
		AREA = new CityArea((String)config.get("AREA_NAME"), 
				   (double[][])config.get("AREA_BBOX"),
				   (String[])config.get("BASE_IN_DIRS"));
		
		DB = (String)config.get("DB"); 
		
		ERLANG_FILES = (String[])config.get("ERLANG_FILES"); 
		
		
		CAT_SET = (String[])config.get("CAT_SET"); 
	}
	
	public void createRankings() throws Exception {
		// this list contains 7 lists of matrixtime, one for each day of the week
		// each list of matrix time, is the erlang matix of a quarter of hour
		List<List<MatrixTime>> erlang_values = load();
		
		
		
		Class.forName("com.mysql.jdbc.Driver").newInstance();
	    Connection c = DriverManager.getConnection(DB);
	    Statement s = c.createStatement();	
		
		double[][] bbox = AREA.getBbox();
	    double minlon = bbox[0][0];
	    double minlat = bbox[0][1];
	    double maxlon = bbox[1][0];
	    double maxlat = bbox[1][1];
	    
	    String points = "'MULTIPOINT("+minlon+" "+minlat+","+maxlon+" "+minlat+","+maxlon+" "+maxlat+","+minlon+" "+maxlat+")'";
	    
	    String where = "";
	    for(String cat: CAT_SET) {
	    	where += "OR category = '"+cat+"' ";
	    }
	    where = where.substring(2).trim();
	    
	    String query = "SELECT idBusiness,AsText(coord) AS coord FROM Business WHERE ("+where+") AND (Intersects(coord,GeomFromText("+points+")));";
	    System.out.println(query);
	
	    
	    ResultSet rs = s.executeQuery(query);
	    DecimalFormat formatter = new DecimalFormat("0.00");
	    formatter.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
	    while(rs.next()) {
	    	int idBusiness = rs.getInt("idBusiness");
	    	String coord = rs.getString("coord");
	    	double lon  = Double.parseDouble(coord.substring(coord.indexOf("(")+1,coord.indexOf(" ")));
	    	double lat  = Double.parseDouble(coord.substring(coord.indexOf(" ")+1,coord.indexOf(")")));
	    	double[][] ranks = getRankings(erlang_values, lon, lat);
	    	
	    	Statement si = c.createStatement();	
	    	for(int d=0; d<ranks.length;d++) {
	    		StringBuffer sb = new StringBuffer();
		    	for(int h=0; h<ranks[d].length;h++)
		    		sb.append(","+formatter.format(ranks[d][h]));
	    		
	    		String insert = "INSERT INTO Rank VALUES("+idBusiness+","+(d+1)+sb.toString()+")";
				System.out.println(insert);
				si.executeUpdate(insert);		
	    	}	 
	    	si.close();
	    }
		
		
	    s.close();
	    c.close();
		System.out.println("Done");
	}
	
	public List<List<MatrixTime>> load() throws Exception {
		
		List<List<MatrixTime>> days = new ArrayList<List<MatrixTime>>();
		for(int i=0; i<ERLANG_FILES.length;i++) {
			ObjectInputStream erlang_in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File(ERLANG_FILES[i]))));
			List<MatrixTime> day_avg = (List<MatrixTime>)erlang_in.readObject();
			erlang_in.close();
			days.add(day_avg);
		}
		
		return days;
	}

	
	public double[][] getRankings(List<List<MatrixTime>> days, double lon, double lat) {
		
		double[][] rankings = new double[7][24];
		
		for(int d=0; d<7;d++) 
		for(int h=0; h<24;h++)  {
			
			if(days.get(d).size() == 24) {
				System.out.println("24 resolution");
				MatrixTime mt = days.get(d).get(h);
				int[] ij = mt.getArea().getij(lon, lat);
				rankings[d][h] = mt.getVal(ij[0],ij[1]);
			}
			else if(days.get(d).size() == 96) {
				System.out.println("96 resolution");
				MatrixTime mt1 = days.get(d).get(4*h);
				MatrixTime mt2 = days.get(d).get(4*h+1);
				MatrixTime mt3 = days.get(d).get(4*h+2);
				MatrixTime mt4 = days.get(d).get(4*h+3);
				int[] ij = mt1.getArea().getij(lon, lat);
				rankings[d][h] = (mt1.getVal(ij[0],ij[1]) + mt2.getVal(ij[0],ij[1])  + mt3.getVal(ij[0],ij[1]) + mt4.getVal(ij[0],ij[1]))/4.0 ;
			}
			else {
				System.out.println("unsuppotred resolution");
				System.exit(0);
			}
		}
		return rankings;
	}
}
